#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "Cube.h"
#include "Processor.h"
#include <unistd.h>

#define NUM_PUZZELS 100

void load(char *fileName, char *data, int length);
void save(char *fileName, char *data, int length);
void simInit();
int simRun();
void simFree();

int main(int argc, char** argv) {
    
    
    /*cubeInit();
    
    int i;
    
    for (i = 0; i < 5; i++) {
        printf("\nCube %d:\n\n", i);
        cubeRandomize();
        cubePrint();
    }
    
    return 0;*/
    
    //Init:
    simInit();
    
    int bestScore = -1000000;
    char *best = NULL;
    
    int n = 0;
    int f = 0;
    while (f < 100) {
        
        //Load program.
        randomize();
        int i;
        for (i = 0; i < MEM_CODE; i++)
            memCode[i] = nextRandom(256);
        
        //execvp("python Generator.py", NULL);
        //load("random.clb", memCode, MEM_CODE);
        
        //Run simualtions.
        int s = 0;
        for (i = 0; i < NUM_PUZZELS; i++)
            s += simRun();
        
        //Handle results
        if (s > bestScore) {
            
            //printf("%6d: %3d\n", n, s);
            
            bestScore = s;
            if (best) free(best);
            best = memCode;
            memCode = malloc(MEM_CODE);
            
            save("best", best, MEM_CODE);
        }
        
        if (s > 400) {
            printf("%2d: %6d: Score: %3d : Best: %3d\n", f, n, s, bestScore);
            
            char name[9] = {'d', '/', '_', '_', '.', 'b', 'u', 'g', 0};
            name[2] = '0' + (f / 10);
            name[3] = '0' + (f % 10);
            
            f++;
            save(name, memCode, MEM_CODE);
        }
        
        n++;
    }

    //Free:
    simFree();

    return 0;
}

void load(char *fileName, char *data, int length) {
    FILE *f = fopen(fileName, "r");
    
    if (fread(data, length, 1, f) != 1) {
        printf("IO error.\n");
        exit(0);
    }
    
    fclose(f);
}

void save(char *fileName, char *data, int length) {
    FILE *f = fopen(fileName, "w");
    
    if (fwrite(data, length, 1, f) != 1) {
        printf("IO error.\n");
        exit(0);
    }
    
    fclose(f);
}

void simInit() {
    cubeInit();
    processorInit();
    memCode = s_malloc(MEM_CODE);
}

int simRun() {
    cubeRandomize();
    int s = cubeScore();
    processorReset();
    processorRun();
    return s - cubeScore();
}

void simFree() {
    free(memCode);
    processorFree();
}
